package com.lyz.tool;

import org.apache.commons.lang.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class PropertiesUtils {

    /**
     * 属性文件与属性集合的关系
     */
    private Map<String, Properties> propertiesMap = new HashMap<>();

    /**
     * 属性文件与修改时间的关系
     */
    private Map<String, Long> modifyTimeMap = new HashMap<>();

    /**
     * 指定的属性文件的目录路径
     */
    private String configPath = "";

    /**
     * 设置文件的目录路径
     */
    public void setConfigPath(String path) {
        this.configPath = path;
    }

    /**
     * 单例模式
     */
    private PropertiesUtils() {}

    public static class SingleHolder {
        private static PropertiesUtils instance = new PropertiesUtils();
    }

    public static PropertiesUtils getInstance() {
        return SingleHolder.instance;
    }

    /**
     * 获取指定属性的值
     */
    public String getPropertyValue(String propertyFileName, String key) throws Exception {
        String fileName = convertFileName(propertyFileName);
        if (propertiesMap.get(fileName) == null) {
            // 如果该配置文件未加载，那么加载指定名称的属性文件
            loadProperties(fileName);
        } else {
            // 如果该配置文件已经加载，检查属性文件有无更新，若更新则重新加载
            checkPropertiesModified(fileName);
        }
        return propertiesMap.get(fileName).getProperty(key);
    }

    /**
     * 检查属性文件有无更新，若更新则重新加载
     */
    private void checkPropertiesModified(String fileName) throws Exception {
        // 拿到file文件
        File file = getPropertiesFile(fileName);
        long newTime = file.lastModified();
        Long lastModifiedTime = modifyTimeMap.get(fileName);
        if (newTime > lastModifiedTime) {
            loadProperties(fileName);
        }
    }

    /**
     * 对传入的属性文件名称进行处理，如果包含.properties后缀则去掉
     */
    private String convertFileName(String fileName) {
        if (!fileName.endsWith(".properties")) {
            return fileName;
        }
        int index = fileName.lastIndexOf(".");
        fileName = fileName.substring(0, index);
        return fileName;
    }

    /**
     * 加载指定名称的属性文件
     */
    private void loadProperties(String fileName) throws Exception {
        // 拿到file文件
        File file = getPropertiesFile(fileName);
        // 获取该文件最新修改时间
        Long newTime = file.lastModified();
        if (propertiesMap.get(fileName) != null) {
            propertiesMap.remove(fileName);
        }
        Properties properties = new Properties();
        properties.load(new FileInputStream(file));
        propertiesMap.put(fileName, properties);
        modifyTimeMap.put(fileName, newTime);
    }

    /**
     * 获取属性文件的路径
     */
    private File getPropertiesFile(String fileName) throws Exception {
        File propertiesFile = null;
        // 1) 如果配置文件路径不为空，则进行拼接
        if (this.configPath != null && !StringUtils.isBlank(configPath)) {
            return new File(this.configPath + File.separator + fileName + ".properties");
        }
        // 2) 如果为空，那么就使用内置的user.dir路径
        String dir = System.getProperty("user.dir") + File.separator + fileName + ".properties";
        // 3) 如果内置路径没有文件，那么就从最终指定路径中查找
        propertiesFile = new File(dir);
        if (!propertiesFile.exists()) {
            // 同级（编译路径）的resource根目录下，是否存在对应文件，存在则返回该地址
            URL url = PropertiesUtils.class.getResource("/" + fileName + ".properties");
            if (url != null) {
                propertiesFile = new File(url.toURI());
            }
        }
        return propertiesFile;
    }

}
